﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using Infragistics.Olap;
using Infragistics.Olap.Data;
using Infragistics.Olap.Data.Base;

namespace PivotGridUsingFlatPivotTable.DataSource
{
	/*
	 * Is overriding DataSourceBase the correct way to start this process of hooking my server
	 * data source to the pivot grid?
     * Yes, you need to use DataSourceBase as base class of your data source since there are few places 
     * where XamPivotGrid is targeting its data source as DataSourceBase 
	 */
	public class FlatPivotDataSource : DataSourceBase
	{
		public FlatPivotDataSource()
		{
		    this.IsFlatData = true;
            this.InitializeAreaItems();
        }        

        private void InitializeAreaItems()
        {
            this.Columns = DataSourceBase.GenerateInitialItems("[Columns].[Columns]");
            this.Rows = DataSourceBase.GenerateInitialItems("[Rows].[Rows]");
            this.Measures = DataSourceBase.GenerateInitialItems("Measure");

            //this.AllowColumnsEditing = false;
            //this.AreaFieldSettings.AllowRowsEditing = false;
            //this.AreaFieldSettings.AllowMeasuresEditing = false;
        }

        private const string PreFilteredMemberGroupsPattern = @"(\{.+?\})?";
        private const string PreLoadedMembersPattern = @"(\[.+?\][\.]?)+";
        protected override void UpdateHierarchiesCollection(AreaItemsCollection hierarchiesCollection)
        {
            string hierarchyNames = hierarchiesCollection.InitialValue;
            if (hierarchyNames != null)
            {
                MatchCollection matches = Regex.Matches(hierarchyNames, PreLoadedMembersPattern + PreFilteredMemberGroupsPattern);
                foreach (Match match in matches)
                {
                    string hierarchyFullQuery = match.Value;

                    Match memberMatch = Regex.Match(hierarchyFullQuery, PreLoadedMembersPattern);
                    IHierarchy hierarchy = (from d in this.Cube.Dimensions
                                            from h in d.Hierarchies
                                            where h.UniqueName == memberMatch.Value
                                            select h).FirstOrDefault();

                    if (hierarchy != null)
                    {
                        this.HasInitializationData = true;

                        IFilterViewModel filterViewModel = this.GetFilterViewModelFromHierarchy(hierarchy);
                        if (filterViewModel == null)
                        {
                            filterViewModel = this.CreateFilterViewModel(hierarchy);
                            this.ExpandFilterMembers(filterViewModel.FilterMembers);
                        }

                        hierarchiesCollection.Add(filterViewModel);
                    }
                }
            }
        }

        private void ExpandFilterMembers(IEnumerable<IFilterMember> filterMembers)
        {
            foreach (FilterMember filterMember in filterMembers)
            {
                filterMember.IsExpanded = true;
                this.ExpandFilterMembers(filterMember.FilterMembers);
            }
        }

		/*
		 * Not sure whether I should be doing this sort of operation here, also not clear to me
		 * how I instruct the data source to refresh data. Not sure how to invoke it (if that's 
		 * what I'm supposed to be doing)
		 */
		protected override void BuildDataInternal(BackgroundWorker backgroundWorker, DoWorkEventArgs e)
		{
            var arg = (object[])e.Argument;
            var dstate=(DataSourceState)arg[1];
            var result= ((FlatPivotDataProvider)this.DataProvider).GenerateResult(dstate);
            e.Result = new object[] {arg[0],arg[1], result, null };
		}

        
        protected override void OnSchemaLoaded(LoadSchemaCompletedEventArgs e)
        {
            base.OnSchemaLoaded(e);
            this.LoadCubesAsync(string.Empty);
        }

        protected override void OnCubesLoaded(LoadCubesCompletedEventArgs e)
        {
            base.OnCubesLoaded(e);
            if (this.Cube == null && this.Cubes != null && this.Cubes.Count > 0)
            {
                this.Cube = this.Cubes[0];
            }
        }
	}
}
